package com.ns.basic.global;

import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.ns.basic.log.utils.ApiLogUtil;
import com.ns.core.utils.jwt.SystemUtil;
import com.ns.core.utils.sg.ResultError;
import com.ns.core.utils.sg.ResultOk;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLException;

/**
 * 全局异常处理
 *
 * <p> @ControllerAdvice 可指定包前缀
 *
 * @author lw
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 全局异常拦截
     */
    @ExceptionHandler
    public ResultOk handlerException(Exception e) {
        // 记录日志信息
        ResultOk aj;
        Throwable e2 = e.getCause();
        // ------------- 判断异常类型，提供个性化提示信息
        // 如果是未登录异常
        if (e.getCause() instanceof TokenExpiredException) {
            aj = ResultOk.getLoginExpire();
        } else if (e.getCause() instanceof FlowException) {
            aj = ResultOk.getError("访问过于频繁，请稍后再试!");
        } else if ((e instanceof SQLException || e2 instanceof SQLException) && SystemUtil.config.isThrowSql()) {
            aj = ResultOk.getError(e2.getMessage());
        } else if (e instanceof org.mybatis.spring.MyBatisSystemException) {
            aj = ResultOk.getError(e2.getMessage());
        } else if (e instanceof RedisSystemException) {
            // 如果是redis连接异常 ( 由于redis连接异常，系统已经无法正常工作，所以此处需要立即返回 )
            aj = ResultOk.getError("Redis异常，请刷新重试");
        } else if (e instanceof RedisConnectionFailureException) {
            aj = ResultOk.getError("Redis异常，请检查连接信息");
        } else if (e instanceof ResultError error) {
            aj = ResultOk.get(error.getCode(), error.getMessage());
        } else {
            // 普通异常输出：500 + 异常信息
            aj = ResultOk.getError(e.getMessage());
        }
        // 插入到日志表
        ApiLogUtil.endRequest(aj);
        // 返回到前台
        aj.set("reqId", ApiLogUtil.getCurrReqId());
        return aj;
    }
}
